%{
#include <kuai/mol/pbc.hpp>

namespace kuai { namespace suan {
	bool getPBC(PyObject* model, const char szname[], PBC** result) 
	{
		if (PyObject_HasAttrString(model, szname)) {
			PyObject* pbc = PyObject_GetAttrString(model, szname);
			assert (pbc != NULL);
			int isOK =  SWIG_ConvertPtr(pbc, (void**)result, SWIGTYPE_p_kuai__PBC, 1);
			if (SWIG_IsOK(isOK)) {
				Py_DECREF(pbc);
				return true;
			}
			else {
				PyObject* str = PyObject_Str(pbc);
				char* strbuffer = PyString_AsString(str);
				bool status;
				try {
					PBC* newvalue = new PBC(PBC::parse(strbuffer));
					PyObject* newptr = SWIG_NewPointerObj(newvalue, SWIGTYPE_p_kuai__PBC, SWIG_POINTER_NEW);
					PyObject_SetAttrString(model, szname, newptr);
					Py_DECREF(pbc);
					*result = newvalue;
					status = true;
				}
				catch (BadLexicalCast&) {
					status = false;
				}
				Py_DECREF(str);
				return status;
			}
		}
		else {
			*result = NULL;
			return true;
		}
	}
} }	
%}

namespace kuai {

	class PBC {
	public:
		explicit PBC();
		explicit PBC(const XYZ& v);
		explicit PBC(const RealNumber& a, const RealNumber& b, const RealNumber& c);
		explicit PBC(const RealNumber& a, const RealNumber& b, const RealNumber& c, const RealNumber& alpha, const RealNumber& beta, const RealNumber& gamma);

	public:
		void update(XYZ& v) const;
		const XYZ image(const XYZ& v) const;

		void scaleX(RealNumber factor);
		void scaleY(RealNumber factor);
		void scaleZ(RealNumber factor);

		void scale(RealNumber x, RealNumber y, RealNumber z);
		void scale(const XYZ& v);
		void scale(RealNumber v);

		PBC& operator*=(const XYZ& v);
		PBC& operator*=(RealNumber v);

		static PBC parse(const String& line);
	};
	
	%extend PBC {
		String __str__() const {
			return str($self);
		}
		
		const RealNumber get_a() const {
			return $self->a();
		}
		const RealNumber get_b() const {
			return $self->b();
		}
		const RealNumber get_c() const {
			return $self->c();
		}

		const XYZ get_va() const {
			return $self->va();
		};
		const XYZ get_vb() const {
			return $self->vb();
		}
		const XYZ get_vc() const {
			return $self->vc();
		}
		
		RealNumber get_volumn() const {
			return $self->volumn();
		}

		const RealNumber get_alpha() const {
			return $self->alpha();
		}
		const RealNumber get_beta() const {
			return $self->beta();
		}
		
		const RealNumber get_gamma() const {
			return $self->gamma();
		}
	};

}	

%pythoncode %{

PBC.a = property(PBC.get_a)
PBC.b = property(PBC.get_b)
PBC.c = property(PBC.get_c)
PBC.alpha = property(PBC.get_alpha)
PBC.beta = property(PBC.get_beta)
PBC.gamma = property(PBC.get_gamma)
PBC.volumn = property(PBC.get_volumn)
PBC.va = property(PBC.get_va)
PBC.vb = property(PBC.get_vb)
PBC.vc = property(PBC.get_vc)

%}
	


